﻿using System;
using System.Linq;
using System.Collections.Generic;

namespace %%%PROJECT_ID%%%
{
	internal static class TranslationHelper
	{
		private static readonly Random random = new Random();

		public static ProgramData ProgramData { get; set; }

		public static readonly bool IsWindows = 
			Environment.OSVersion.Platform == PlatformID.Win32NT ||
			Environment.OSVersion.Platform == PlatformID.Win32S ||
			Environment.OSVersion.Platform == PlatformID.Win32Windows ||
			Environment.OSVersion.Platform == PlatformID.WinCE;

		public static void ShuffleInPlace(List<Value> list)
		{
			if (list.Count < 2) return;

			int length = list.Count;
			int tIndex;
			Value tValue;
			for (int i = length - 1; i >= 0; --i)
			{
				tIndex = random.Next(length);
				tValue = list[tIndex];
				list[tIndex] = list[i];
				list[i] = tValue;
			}
		}

		public static double GetRandomNumber()
		{
			return random.NextDouble();
		}

		public static List<Value> ValueListConcat(List<Value> a, List<Value> b)
		{
			List<Value> output = new List<Value>(a.Count + b.Count);
			output.AddRange(a);
			output.AddRange(b);
			return output;
		}

		public static List<Value> MultiplyList(List<Value> items, int times)
		{
			List<Value> output = new List<Value>(items.Count * times);
			while (times-- > 0)
			{
				output.AddRange(items);
			}
			return output;
		}

		public static List<T> NewListOfSize<T>(int size)
		{
			List<T> output = new List<T>(size);
			while (size-- > 0)
			{
				output.Add(default(T));
			}
			return output;
		}
		
		private static readonly string[] SPLIT_SEP = new string[1];

		public static string[] StringSplit(string value, string sep)
		{
			if (sep.Length == 1)
			{
				return value.Split(sep[0]);
			}

			if (sep.Length == 0)
			{
				return value.ToCharArray().Select<char, string>(c => "" + c).ToArray();
			}

			SPLIT_SEP[0] = sep;
			return value.Split(SPLIT_SEP, StringSplitOptions.None);
		}

		public static string StringReverse(string value)
		{
			if (value.Length < 2) return value;
			System.Text.StringBuilder sb = new System.Text.StringBuilder();
			for (int i = value.Length - 1; i >= 0; --i)
			{
				sb.Append(value[i]);
			}
			return sb.ToString();
		}

		public static object ImagetteFlushToNativeBitmap(Imagette img)
		{
			System.Drawing.Bitmap target = new System.Drawing.Bitmap(img.width, img.height);
			target.SetResolution(96, 96);
			System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(target);
			for (int i = img.nativeBitmaps.Count - 1; i >= 0; i--)
			{
				System.Drawing.Bitmap source = (System.Drawing.Bitmap)img.nativeBitmaps[i];
				int x = img.xs[i];
				int y = img.ys[i];
				g.DrawImage(source, x, y);
			}
			g.Flush();
			return target;
		}

		public static void DownloadImageFromInternetTubes(string key, string url)
		{
			System.ComponentModel.BackgroundWorker bgWorker = new System.ComponentModel.BackgroundWorker();
			bgWorker.DoWork += (sender, args) =>
			{
				System.Net.WebClient wc = new System.Net.WebClient();
				try
				{
					byte[] imageBytes = wc.DownloadData(url);
					System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(new System.IO.MemoryStream(imageBytes));
					bmp.SetResolution(96, 96);
					args.Result = bmp;
				}
				catch (Exception)
				{
					args.Result = null;
				}
			};
			bgWorker.RunWorkerCompleted += (sender, args) =>
			{
				CrayonWrapper.v_imageDownloadCompletionHandler(key, args.Result);
			};
			bgWorker.RunWorkerAsync();
		}

		public static void Assertion(string message)
		{
			throw new Exception(message);
		}
		
		public static void SortPrimitiveValueList(List<Value> valueList, bool isString)
		{
			Value[] orderedList;
			if (isString)
			{
				orderedList = valueList.OrderBy<Value, string>(v => (string)v.internalValue).ToArray();
			}
			else
			{
				orderedList = valueList.OrderBy<Value, double>(v => v.type == %%%TYPE_INTEGER%%% ? (double)(int)v.internalValue : (double)v.internalValue).ToArray();
			}
			for (int i = orderedList.Length - 1; i >= 0; --i)
			{
				valueList[i] = orderedList[i];
			}
		}

		public static SoundInstance GetSoundInstance(string path)
		{
			IList<byte> resource = ResourceReader.ReadBytes(path, true);
			if (resource == null) return null;
			SdlDotNet.Audio.Sound sdlSound = new SdlDotNet.Audio.Sound(resource.ToArray());
			// TODO: determine length of sound.
			return new SoundInstance(sdlSound, false, -1, 0);
		}

		public static void PlaySoundInstance(SoundInstance sound)
		{
			SdlDotNet.Audio.Sound sdlSound = (SdlDotNet.Audio.Sound)sound.nativeObject;
			sdlSound.Play();
		}

		public static bool DoesPathExist(string path, bool directoriesOnly, bool checkCase)
		{
			// TODO: check the case.
			if (System.IO.Directory.Exists(path))
			{
				return true;
			}

			if (!directoriesOnly && System.IO.File.Exists(path))
			{
				return true;
			}

			return false;
		}

		public static string[] FilesInDirectory(string path)
		{
			if (!path.Contains("\\") && path.Contains(":"))
			{
				path += "\\";
			}
			List<string> files = new List<string>();
			files.AddRange(System.IO.Directory.GetFiles(path));
			files.AddRange(System.IO.Directory.GetDirectories(path));
			HashSet<string> output = new HashSet<string>(files);
			return output.Select<string, string>(s => s.Substring((path.EndsWith("\\") ? 0 : 1) + path.Length)).OrderBy(s => s).ToArray();
		}

		public static int WriteFile(string path, string contents)
		{
			try
			{
				System.IO.File.WriteAllText(path, contents);
			}
			catch (UnauthorizedAccessException)
			{
				return 1;
			}
			catch (System.IO.PathTooLongException)
			{
				return 2;
			}
			catch (System.IO.IOException)
			{
				return 3;
			}
			catch (Exception)
			{
				return 4;
			}
			return 0;
		}

		public static string ReadFile(string path)
		{
			try
			{
				return System.IO.File.ReadAllText(path);
			}
			catch (Exception)
			{
				return null;
			}
		}
	}
}
